#include <jni.h>
#include <linux/seccomp.h>
#include <sys/prctl.h>
#include <stdio.h>
#include <sys/ptrace.h>
#include <string.h>
#include <dlfcn.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include <android/log.h>
#include <errno.h>
#include "logging.h"

//
// Created by Administrator on 2025/4/21.
//
static volatile sig_atomic_t timeout = 0;

#define TAG "RootDetectorPlus"

void alarm_handler(int sig  __unused) {
    timeout = 1;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zx_sercurity_rootdetectorplus_detector_NativeChecks_checkSeccomp(JNIEnv *env  __unused,
                                                                          jclass clazz  __unused) {
    LOGI("Starting checkSeccomp");
    
    // 设置超时处理
    signal(SIGALRM, alarm_handler);
    alarm(2); // 2秒超时

    int mode = -1;

    // 尝试获取seccomp模式
    mode = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
    
    LOGI("Seccomp mode: %d", mode);

    // 取消超时
    alarm(0);

    if (timeout) {
        LOGE("checkSeccomp timeout");
        return 2; // 超时状态
    }

    if (mode == -1) {
        LOGE("prctl failed");
        return 3; // prctl调用失败
    }

    if (mode != SECCOMP_MODE_FILTER) {
        LOGI("Abnormal seccomp mode");
        return 1; // 非正常状态
    }

    LOGI("Normal seccomp mode");
    return 0; // 正常状态
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_zx_sercurity_rootdetectorplus_detector_NativeChecks_checkSelinuxEnforce(JNIEnv *env  __unused,
                                                                                 jclass clazz  __unused) {
    FILE *f = fopen("/sys/fs/selinux/enforce", "r");
    if (!f) return -1;
    char buf[8];
    fgets(buf, sizeof(buf), f);
    fclose(f);
    return buf[0] != '1'; // 非强制
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zx_sercurity_rootdetectorplus_detector_NativeChecks_checkPtrace(JNIEnv *env  __unused,
                                                                         jclass clazz  __unused) {
    errno = 0;
    int result = ptrace(PTRACE_TRACEME, 0, 0, 0);
    int err = errno;

    LOGI("ptrace() result: %d, errno: %d (%s)", result, err, strerror(err));

    if (result == -1) {
        if (err == EPERM || err == EBUSY) {
            return 1; // 正在被调试 or 权限问题
        } else {
            return 2; // 其他失败
        }
    }

    ptrace(PTRACE_DETACH, 0, 0, 0);
    return 0; // 正常
}

// 将whitelist数组定义为全局常量
static const char* const whitelist[] = {
        "[anon:dalvik",
        "[anon:libc_malloc",
        "[anon:scudo",
        "[stack",
        "[anon:.bss",
        "/data/app/",
        "/data/data/",
        "memfd:jit-",
        "memfd:jit-zygote",
        "memfd:ashmem",
        "/dev/ashmem",
        "/system/fonts/",
        "/system/etc/",
        "[anon:thread",
        "[anon:linker_alloc",
        "[vdso]",  // 虚拟动态共享对象
        "[vsyscall]", // 旧版系统调用跳板
        "[vectors]", // ARM架构的异常向量表
        NULL  // 结束标记
};

// 检查是否为白名单条目
static int is_whitelisted(const char* line) {
    for (int i = 0; whitelist[i] != NULL; i++) {
        if (strstr(line, whitelist[i])) {
            LOGD("Whitelisted: %s", whitelist[i]);
            return 1;
        }
    }
    return 0;
}

// 检查可疑的内存映射模式
static int is_suspicious_pattern(const char* line) {
    // 可疑的可执行匿名内存
    if (strstr(line, "rwxp") && strstr(line, "[anon:")) {
        LOGD("Suspicious executable anonymous memory: %s", line);
        return 1;
    }

    // 非常规memfd
    if (strstr(line, "memfd:") && !strstr(line, "jit-") && !strstr(line, "ashmem")) {
        LOGD("Suspicious memfd mapping: %s", line);
        return 1;
    }

    // 隐藏的so库
    if (strstr(line, ".so") && strstr(line, "/data/") &&
        !strstr(line, "/data/app/") && !strstr(line, "/data/data/")) {
        LOGD("Suspicious so in /data: %s", line);
        return 1;
    }

    // 没有文件路径的可执行内存
    if (strstr(line, "r-xp") && strstr(line, " 00:00 0 ")) {
        LOGD("Suspicious anonymous executable: %s", line);
        return 1;
    }

    return 0;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zx_sercurity_rootdetectorplus_detector_NativeChecks_checkAnonymousMaps(
        JNIEnv* env __unused, jclass clazz __unused) {

    FILE* fp = fopen("/proc/self/maps", "r");
    if (!fp) {
        LOGD("Failed to open /proc/self/maps");
        return -1;
    }

    volatile int suspicious = 0;  // 使用volatile防止优化
    char line[1024] = {0};       // 明确初始化缓冲区

    while (fgets(line, sizeof(line)-1, fp)) {  // 保留空间给null终止符
        // 确保字符串正确终止
        line[sizeof(line)-1] = '\0';

        // 跳过空行和注释
        if (line[0] == '\0' || line[0] == '\n') continue;

        LOGD("Analyzing line: %.*s", (int)strlen(line)-1, line);  // 避免打印换行符

        // 检查白名单
        if (is_whitelisted(line)) {
            LOGD("Line whitelisted");
            continue;
        }

        // 检查可疑模式
        int pattern_result = is_suspicious_pattern(line);
        LOGD("is_suspicious_pattern returned: %d", pattern_result);

        if (pattern_result) {
            LOGD("Suspicious pattern detected: %.*s", (int)strlen(line)-1, line);
            suspicious = 1;
            break;
        }
    }

    fclose(fp);
    LOGD("Final suspicious value: %d", suspicious);
    return suspicious;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zx_sercurity_rootdetectorplus_detector_NativeChecks_checkLibcHook(JNIEnv *env  __unused,
                                                                           jclass clazz  __unused) {
    void* addr = dlsym(RTLD_NEXT, "open");
    void* real_addr = dlsym(RTLD_DEFAULT, "open");
    return addr != real_addr; // 地址不一致可能被hook
}